Approaching Be
An introduction to programming for the BeOS

As the Be Operating System (BeOS ) has emerged onto the computing landscape, thousands 
of software developers have been attracted to its feature set, simplicity and performance. 
 This interest has been amplified by the introduction of versions of the BeOS that can 
 run on mainstream PowerPC systems, such as PowerMacintosh and its clones. 
 As interest has risen, one of the questions we get most often from programmers is, 
"Where do I start?"

Programming for the BeOS is similar in many ways to programming for other operating 
systems   at least those that can be considered "modern."  But there are fundamental 
differences in the design and goals which can affect how you might structure your 
application.  Programmers want to understand those fundamental design goals and the philosophy 
of the OS design before they start to write code.

This white paper is designed to answer this set of basic questions.  It is written 
with the programmer in mind, though some non-programmers may find it useful as well. 
 It is also written to be useful from the perspective of the programmer coming to 
the BeOS from a MacOS or Windows environment.  Many of the topics will be discussed in a 
way that compares the BeOS approach with those used by these other systems.

The content is broken into three sections.  The first will discuss the underlying 
fundamental design and philosophy  of the BeOS and how they might impact the design 
of your software.  The second section will discuss the general architecture of the 
BeOS and identify the key components a programmer deals with.  In the third section, we'll 
walk through the creation of a basic, simple application.

There are a number of other white papers and primers available that build on this 
document.  These can be found in the Developer section of the Be web site at http://www.be.com.


Fundamental Concepts

In creating the BeOS, the Be engineering team has used a set of fundamental assumptions 
and concepts as guides.  These concepts are so ingrained in the OS that they can 
have important impacts on how you might architect your own applications.  If you 
are approaching the BeOS from the MacOS space, or even the Windows space, it's also important 
to understand where the BeOS differs   many of the differences lie in these fundamental 
concepts.

One common joke around the Be offices is that "BeOS" actually stands for "buzzword 
enabled operating system."  Without a doubt, the BeOS meets and exceeds the market 
expectations of what a "modern" operating system should look like.  Five of these 
buzzword concepts are important to understand because they impact the design of software written 
for the BeOS; object-orientation, preemptive multitasking, protected memory, symmetric 
multiprocessing and extensive multithreading.


Object-Orientation

Probably the most significant difference between the BeOS and current mainstream operating 
systems is that the BeOS is an object-oriented
 operating system.  This means that its application programming interface (API) is 
composed of objects, rather than the procedure calls you might find in the MacOS 
or Windows.  When you create an application for the BeOS, you will create a derivative 
of the basic BApplication object, and you will use either the standard objects built into 
the BeOS such as BWindow and BButton, or derivatives of these objects.

Object-oriented programming has been around for awhile, but it is only recently that 
software development has utilized its basic concepts.  The BeOS is one of the few 
operating systems to base itself entirely upon the object-oriented concept.  When 
looking at the BeBook, the reference book that describes the entire BeOS API, you won't find 
a set of procedures.  What you will find is an entire application framework, with 
objects that can be linked together to create an application, create its windows 
and interface, manage network connections, and manipulate most of the data objects you'll 
create within your application.  These objects contain a large amount of functionality 
built-in   you won't need to start from scratch nor connect separate procedures into 
complex chains.  A lot of the basic work is already done for you.  And further, you'll 
be able to use objects created by other BeOS programmers within your application 
as well.

But what this means is that within in the BeOS, you'll need to program in an object-oriented 
language.  The BeOS API is based on C++.  Java, a close cousin of C++, will also 
be supported in the future.  Be chose these languages because they are based on industry 
standards and have the support of a wide range of vendors.

If you understand object-oriented concepts, and have used C++, you'll have no problems 
jumping into the BeOS.  If you have programmed on the MacOS, and have used an application 
framework such as Metrowerk's PowerPlant or Apple's MacApp, you are even in a better position 
because the BeOS API will look very familiar to you.  Likewise, if 
you have used Microsoft Foundation Classes for Windows, you will recognize many of 
the concepts found in the BeOS.

If you don't know C++ or Java, but would like to learn about object-oriented programming, 
the BeOS is a great place to start because it is a new, relatively uncluttered operating 
system that is built on object-oriented concepts.  So you won't have to deal with a lot of 
exceptions and work-arounds in the API that you might find in other 
systems.

Preemptive Multitasking

Most programmers are familiar with multitasking - the ability to run more than one 
application at a time and have the operating system worry about splitting CPU time 
between them.  Preemptive
 multitasking goes a step further, and it's important to understand the difference, 
especially if you are coming from the MacOS.  Several operating systems, including 
the MacOS, use a system known as cooperative multitasking, which means that each 
application must voluntarily give up time so that other applications can continue running. 
 In the MacOS, this system is represented by the WaitNextEvent() procedure call, 
which turns control back to the OS until another event is detected.  Of course, if 
an application does not call WaitNextEvent(), or delays calling it, other applications may 
have trouble executing in a smooth fashion.

Preemptive multitasking eliminates the need for something like WaitNextEvent().  In 
a preemptive system like the BeOS, the operating system itself allows each application 
to execute for a specific period of time, depending upon its priority and the number 
of tasks currently executing in the system.  When that time is up, the BeOS will stop 
the application, no matter what it is doing, and pass control onto the next process.  
This results is a much smoother and more interactive system for the user.

Of course, what this also means is that you, as a programmer, must always remember 
that your application can be interrupted at any time.  Usually, you don't need to 
do anything differently under this system.  But if you are accessing a shared resource, 
it's possible that other processes sharing that resource will jump in (or out) during 
your "suspended" state, and that may affect you.  Remember, unlike cooperative multitasking, 
you won't necessarily be guaranteed to finish a sequence of instructions before the OS 
switches your code out.  There are ways of telling the OS how important certain 
tasks are (such as real-time audio or video, etc.) and there are ways of locking 
resources if needed.  We'll talk more about that in a bit.


Protected Memory


One of the key complaints users have about personal computer systems is how often 
applications crash, and in doing so lock up their entire machine.  The reason for 
this is that the failed application has usually attempted to alter physical memory 
owned by another application, or by the operating system itself.  These changes quickly ripple 
through the system and cause both the application and entire machine to crash.

To prevent this, the BeOS uses a scheme known as protected memory.  What this means 
is that the memory owned by one process cannot be accessed by any other process. 
 When an application starts up under the BeOS, it is told that it has the entire 
logical address space (currently 32-bits or 4 gb of memory) all to itself.  Applications under 
the BeOS use pointers or other direct references to memory.  If you are coming from 
Windows, this is pretty much old hat, but the MacOS often uses indirect memory "handles" to 
allow for memory management.

Of course, most real computers don't have 4 gb of memory installed.  The BeOS therefore 
keeps a close watch on each application's real
 memory use.  It breaks down the entire 4 gb memory space into "pages" and then keeps 
track of how many pages are used, and how often each page is accessed.  If more physical 
memory is needed by another process, the BeOS will temporarily unload several least-used 
pages onto disk to make room, and will reload those pages when needed again. 
 This is the real meaning behind "virtual memory."  Within the BeOS (as well as within 
Unix, Windows NT and other modern operating systems) virtual memory is always
 on.
 
Protected memory goes a long way towards keeping a system stable.  If you are writing 
applications, servers or many other pieces of code, you'll have difficulty bringing 
the system down.  Another one of the reasons for this is that the BeOS is built upon 
a "client-server" architecture where system resources such as the screen or networking 
hardware are controlled by a "server" which multiple "clients" talk to in order to 
gain access.  All applications lie on the client side of this architecture.  This 
provides a further level of protection by minimizing resource collisions.  If you are one 
of the developers creating code that lies on the server side of the architecture, 
such as hardware drivers, you'll need to make sure your code is simple, fast and 
bullet-proof.  The BeBook provides further advice for building this type of software.



Symmetric Multiprocessing

Another key limitation of most mainstream operating systems today is an assumption 
that there is only one microprocessor per system.  Although some systems, like the 
MacOS, can make limited use of a second processor, most OSes were not designed with 
multiprocessing in mind.

The BeOS was designed as a multiprocessor OS from the beginning.  The initial systems 
it was created on all used two microprocessors, and the BeOS now runs on systems 
containing one to four processors.  The BeOS itself is not limited   it can support 
"n" processors in theory   although realistically there are significant limitations today 
in mainstream hardware implementations once you pass about eight processors.

Further, the implementation of multiprocessing in the BeOS is "symmetric."  As a programmer, 
you do not have to worry about which processor your application uses at any particular 
point in time.  In designing a BeOS application, you do nothing differently in order to run 
on single processor systems and eight processor systems (although 
you may want to take the number of processors into account in a few calculation-intensive 
cases for optimization purposes)  Your application may start on one processor, move 
to another processor, and move back many times during execution.  All of this is transparent 
to your code.

But one thing that symmetric multiprocessing implies is that you can create applications 
that do many (many, many) things in parallel.  And in order to do this, there is 
one last BeOS concept that you need to keep in mind...


Extensive Multithreading

In traditional operating systems, each application can be thought of as a single "thread" 
of execution, from the top of the code to the eventual end.  If you have multiple 
applications open, there are multiple threads of execution happening at once, and 
they share the processor(s) time.

In the BeOS, threading goes much further.  In order to take maximum advantage of multiple 
processors, each application
 should be broken down into multiple threads of execution.  If an application has 
a single thread, then it must execute on only one processor at a time (although that 
processor may change during execution.)  But if an application has multiple threads, 
then that application can make use of multiple processors in parallel.  This can vastly
 improve the execution time of code.
 
In testing various execution models, we've found out that breaking an application 
into multiple threads can make overall execution and task switching faster and smoother, 
even on single processor systems.  
It turns out that extensive threading aids and amplifies the affect of preemptive 
multitasking.

Knowing this, the BeOS itself is heavily threaded.  Even at a complete standstill, 
the BeOS makes use of dozens of threads.  Every server in the system spawns threads 
constantly.  Further, it is virtually impossible to write an application that is 
not threaded.  In creating a BApplication object, two threads are automatically created for 
you, and are managed by the BApplication object (you'll need to do nothing other 
than use the application object.)  Every window in the BeOS creates two threads   
thus every window can theoretically run on its own processor.  Multithreading, symmetric multiprocessing, 
and preemptive multitasking all build on each other, and its this synergy which allows 
the BeOS to deliver much of its power.

Other than the object-oriented nature of the BeOS, multithreading has perhaps the 
most significant impact on software design.  Luckily, object-orientation and threading 
go hand-in-hand.  If you are coming to the BeOS from either the MacOS or Windows, 
there are two things involving threading to keep in mind;


Think of each thread as an "event-loop"

Both the MacOS and Windows use the concept of an application event-loop through which 
all events from the real-world (mouse-clicks, key presses, etc.) pass.  You can think 
of each thread in the BeOS as a separate event-loop.  This means that each application 
has multiple event-loops, not just one.   In the BeOS, a mouse-click in a window 
will not pass through an application-wide event loop, it will be delivered directly 
to the window thread.  This also means that an application may be processing multiple 
events at once.  Sounds a bit complex, but it's actually quite simple because in an 
object-oriented system, each object worries only about its own events.  Thus code 
is usually much simpler and cleaner than in single event-loop systems.

Now, take the above paragraph, and replace the word "events" with the word "messages." 
 In the BeOS, the "event-loop" is referred to as the "message loop."  This is because 
each thread can deal with a much wider range of messages than simply a set of real-world 
mouse clicks and key presses.  You can find more information about threads 
by reading about the BLooper and BHandler objects in the BeBook (and looking at which 
object inherit from these), and more about messages by looking at the BMessage and 
BMessenger objects.
 You may need to "lock" objects 
Multiple threads mean multiple things can happen at the same time.  What happens if 
an object attempts to change a value that's part of a BWindow object at the same 
time that BWindow is drawing itself?  The results can be interesting.  You can prevent 
these conflicts by locking an object that you are using, if necessary, and unlocking 
it afterwards.  During the lock period, one process has exclusive access to an object. 
 For those of you familiar with threading, this might sound a lot like the concept 
of a "semaphore."  You're right, they are exactly the same.  You can find out more about 
locks by looking at the BLocker object in the BeBook.



System Architecture

Now that we've described the basic concepts underlying the BeOS, we can outline the 
architecture of the system in a more concrete fashion.  The block diagram below provides 
an overview of the components of the BeOS;



The BeOS can be divided into three main groups of components; the Kernel, the BeOS 
Servers, and the BeOS Kits.

The Kernel

The BeOS employs a microkernel to abstract the hardware and to provide basic OS services. 
As you might expect, the BeOS kernel is optimized to take advantage of multiple processors, 
and for handling large numbers of simultaneously executing threads. Kernel capabilities can 
be extended through software drivers, which are dynamically loaded 
and unloaded as needed by the system.


BeOS Servers

An array of software servers encapsulate key areas of functionality used by applications 
and by the OS itself, and represent the heart of the BeOS. Examples of these servers 
are the App Server
, which provides graphics services, the Storage Server
, which provides file system and database functionality, the Network Server
, which provides TCP/IP capabilities, and the Audio Server
, which handles real-time audio streams from a variety of sources. These servers are 
automatically started at system start-up, are designed around a client-server model, 
and are heavily threaded themselves.

BeOS Kits 
Applications never access the BeOS servers directly.  Rather, applications make use 
of the BeOS Kits, which in turn know how to interface with each server.  Each Kit 
is made up of a set of C++ objects, which can be used and subclassed.   These objects 
in turn call the servers   and each other   to accomplish more complex tasks. Examples 
of the BeOS Kits are the Interface Kit,
 handling most window, view, and drawing functions, the Application Kit
, handling application-level capabilities and communications, and the Media Kit,
 handling audio and video capabilities.  The array of BeOS software kits provide a 
wide range of classes and functions that applications use to build complex capabilities. 
These Kits are constantly being extended and improved by Be through each release 
of the BeOS. 

A sampling of the core BeOS software kits found in the BeBook include;

Application Kit 

Contains core application objects, such as BApplication, BMessage (for communications), 
and BLooper (for creating new threads). 


Storage Kit

One of the key advantages of the BeOS is that is provides both file system capabilities 
and integrated database capabilities. The Storage Kit works with the Storage Server 
to provide objects such as BFile, BDirectory, and BDatabase. 


Interface Kit 

The largest of the kits, the Interface Kit works with the Application Server to provide 
objects such as BWindow and BView, which provide the basis for other interface objects 
such as BListView, BCheckBox, BTextView, and many others. The Interface Kit (through BView) 
also encapsulates all drawing capabilities. 


Media Kit 

The Media Kit handles real-time streams of data through the system which means it's 
the kit that deals with audio and video streams. The kit employs a &quot;subscriber&quot; model, 
through objects such as BAudioSubscriber, which allows multiple processes to access 
and manipulate a single stream of data. 


Midi Kit 

This kit provides a set of classes that know how to decipher and construct MIDI messages 
and that can listen to and broadcast to hardware MIDI ports, or communicate with 
the built-in software MIDI synthesizer


Device Kit 

This kit provides a generalized interface for building drivers that extend the capabilities 
of the kernel   such as hardware drivers, graphics drivers and others. It also includes 
such objects as BSerialPort. 


Network Kit 

The Network Kit provides TCP/IP services based on the Berkeley Sockets  (BSD) model. 
It also provides classes that know how to send and receive e-mail.


3D Kit

The 3D Kit offers a 3-D rendering engine and classes with which a developer can easily 
construct and manipulate interactive 3-D graphics. This kit will be expanded in the 
future to incorporate the OpenGL standard.

The servers and kits work closely together, and in most cases the kits are simply 
the interface through which applications make requests of the servers.  For example, 
if during a draw method you draw a line into a window;


In this case, you've created a BView object in your code (BViews are responsible for 
any drawing on the screen, or off it for that matter.)  Each view has a Draw() method 
which you write to give the view a distinctive appearance (if it wasn't unique, you'd simply 
use one of the standard view objects in the Interface kit and forget about 
writing a Draw() method.)  The Draw() method would call the built-in StrokeLine() 
method to draw the line.  StrokeLine() actually sends a message to the App_Server, 
telling it to draw the line, and then it returns immediately.  While the next line of your 
view Draw() code is executing, the App_Server is busy drawing the line (there's that 
multithreading concept again) by calling the appropriate drivers (there may be acceleration 
code in the hardware, for example) to change the screen buffer.


Thus the objects in the BeOS kits correspond to a BeOS server.  Here are some of the 
kits and the corresponding servers they communicate with;

Application KitApp_Server and Kernel
Storage KitStorage_Server (File System)
Interface KitApp_Server
Media KitAudio_Server and Video_Server
MIDI KitAudio_Server
3D KitApp_Server
Kernel KitKernel
Device KitKernel
Game KitApp_Server
Network KitNet_Server and Mail_Daemon


Now that we've built a foundation of BeOS concepts, the best way to understand how 
they fit together is to write an application.  To do this, we'll look at a BeOS implementation 
of a simple application, HelloWorld.  The discussion in the next session assumes that you 
understand the basics of C++.


HelloWorld Application

HelloWorld will do a few simple things.  At startup, it will create a window.  Within 
that window it will write the words "Hello, World!".  HelloWorld will also create 
a main menu with an "About..." item and a "Quit" item.  Choosing About from the main 
menu will show a standard About dialog.   Choosing quit from the main menu or closing 
the window will cause the application to quit.



What we'll find in creating this application is that most of the work is already done 
for us in the basic BeOS objects.  We're going to define each object with a header 
file and an implementation file.  With such a simple application, we could take shortcuts 
and place the code in fewer files, even one, but the purpose here is to write HelloWorld 
in a way similar to how you'd write a full-blown application.

First off, we need to create the application object.   The interface to this object 
is simple and straightforward;


// -----------------------------------------------------------------------
// HelloWorldApp.h
// -----------------------------------------------------------------------
     #pragma once

     #include &lt;Application.h&gt;

     class HelloWorldApp          : public BApplication
     {
          public:
               HelloWorldApp();
     };


The #pragma once line should be placed at the front of any header file you create.  CodeWarrior uses 
this to ensure that no header is accidentally included twice.  This is simpler than 
#define, #if and #endif statements which can be used to do the same, though #pragma once is 
not as portable across development systems.

The next line includes the BeOS BApplication definitions.  Since HelloWorldApp will be a subclass of the 
general BApplication object, we need to include these definitions.

The HelloWorldApp class is defined next, and is very simple.  HelloWorldApp is a subclass 
of BApplication.  It inherits all of the normal behavior of a BeOS application, which 
includes a main menu with an about box and quit command.  It also inherits a main thread for 
the application itself.

There is only one new method defined in this simple example, a constructor for the 
class, HelloWorldApp().  We'll use the constructor to create the application's window.

The implementation of the HelloWorldApp is equally simple;


// -----------------------------------------------------------------------
// HelloWorldApp.cp
// -----------------------------------------------------------------------
     
     #include "HelloWorldApp.h"
     // other includes go here

     main()
     {
          HelloWorldApp*     myApplication;
          myApplication = new HelloWorldApp();
          myApplication-&gt;Run();
          delete myApplication;
          return 0;    
     }


     HelloWorldApp::HelloWorldApp()     : BApplication('HLWD')
     {
          // Set up windows and stuff
     }

For clarity, we've commented out the window creation code.  We'll get to that in a 
minute.  As with any C and C++ application, a main() routine is required.  In this case, 
main() is simple and looks pretty much the same no matter how complex your application might 
be.  main() allocates a pointer for an application of type "HelloWorldApp" and then creates the 
application object in the next line.  Then the application is started by sending 
it Run().  Run() embodies the main thread of the application, and so does not return until the application 
has been instructed to quit.  When that happens, main() deletes the myApplication object, 
and for completeness returns 0 as an overall result (this last line is not strictly necessary.)

The only other routine in the implementation is the HelloWorldApp() constructor.  Since 
HelloWorldApp is derived from BApplication, we allow the BApplication 
constructor to execute and send it the applications' creator signature 'HLWD'.  We'll 
return to this constructor after we define the HelloWindow object.

The window we need to create is actually made up of two objects.  There is the window 
itself, and within the window there will be a view that draws the "Hello, World!" 
text.  We'll start at the bottom of this ladder, and define the view first.


// -----------------------------------------------------------------------
// HelloView.h
// -----------------------------------------------------------------------
     #pragma once

     #include &lt;View.h&gt;

     class HelloView          : public BView
     {
          public:
                                    HelloView(BRect frame, char* name);
               virtual     void     AttachedToWindow();                   // Override
               virtual     bool     Draw(BRect updateRect);               // Override
     };

// -----------------------------------------------------------------------
// HelloView.cp
// -----------------------------------------------------------------------
     #include "HelloView.h"

     HelloView::HelloView(BRect frame, char* name)
                    : BView(frame, name, B_FOLLOW_ALL, B_WILL_DRAW)
     {
     }

     void
     HelloView::AttachedToWindow()
     {
          SetFontName("Times New Roman");
          SetFontSize(24);
     }

     void
     HelloView::Draw(BRect /*updateRect*/);
     {
          MovePenTo(10, 30);
          DrawString("Hello, World!");
     };
  
In the header, HelloView is defined as a subclass of the general BView object.  There 
are a myriad of objects in the BeOS which derive from BView - almost anything that 
draws on the screen is a BView object, because that's what BView is designed to do. 
 BViews also have the ability to contain other views.   In the definition we provide 
a constructor, and we redefine -- as called "override" - two methods that are defined 
by BView; AttachedToWindow() and Draw().

In the implementation, we provide an empty constructor whose purpose is to pass along 
arguments to the BView constructor.  We pass the frame of the view, provided as a 
BRect rectangle object, and the name of the view (which can be used by more complex 
applications to find and manipulate the view.)  We also pass two other arguments.  The 
first, B_FOLLOW_ALL instructs the HelloView to resize itself to fit the window it's in whenever the window's 
size changes.  By doing this, we don't have to worry about window changes, the underlying 
BView object has that functionality built in.  The second parameter, B_WILL_DRAW, will 
tell the window the view is in that HelloView draws on the screen (rather than 
being merely a container for other views) and should be told whenever an screen update 
is needed.

AttachedToWindow() is a method that is called when the view is "attached" to a window.  
AttachedToWindow() is referred to as a "hook" method in the BeOS - the default does nothing but the 
method is provided so that we can override it to finish setting up a view when it 
is attached.  In HelloView, we simply want to set up the font and font size for the 
view.

Draw() is another "hook" method.  In this case, Draw() is called whenever the screen 
changes such that the view needs to redraw its contents. 
 Most BView derived objects will override Draw().  The argument updateRect provides the 
 area that needs to be updated.  In this case, 
we can ignore this argument since the contents are simple and quickly redrawn.  We 
simply move the view's pen to (10,30) and draw the string "Hello, World!" in the 
current font and size (set in advance by AttachedToWindow().)

Now that we have the view defined, we can define the window.

// -----------------------------------------------------------------------
// HelloWindow.h
// -----------------------------------------------------------------------
     #pragma once

     #include &lt;Window.h&gt;

     class HelloWindow          : public BWindow
     {
          public:
                                    HelloWindow(BRect frame);
               virtual     bool     QuitRequested();             //Override
     };

// -----------------------------------------------------------------------
// HelloWindow.cp
// -----------------------------------------------------------------------
     #include "HelloWindow.h"
     #include "HelloView.h"

     HelloWindow::HelloWindow(BRect frame)     
                 :BWindow(frame, "Hello", B_TITLED_WINDOW, B_NOT_RESIZABLE)
     {
          BRect       viewRect = Bounds();
          HelloView*  theView = new HelloView(viewRect, "HelloView");
          AddChild(theView);
          Show();
     }


     HelloWindow::QuitRequested()
     {
          be_app-&gt;PostMessage(B_QUIT_REQUESTED);
          return true;
     }
 

The HelloWindow class only has two features unique to it over the BWindow class it 
derives from; a constructor and an override of the QuitRequested() hook method.

In the constructor, we pass the arguments to the inherited BWindow constructor.  frame 
determines where the window is placed on the screen.  "Hello" is the title of the 
window, used in the window's title bar (if it has one, which in this case it does.) 
 B_TITLED_WINDOW sets the type of the window to a normal movable window with a titlebar at top, and 
B_NOT_RESIZABLE fixes the window size as unchanging.

Within the constructor itself, we create a HelloView object.  To get the correct size 
for the view, we can get the HelloWindow bounds rectangle by calling the built-in 
Bounds() method.  We then call the window's AddChild() method to install the view inside 
the window.  Lastly, we cause the HelloWindow to 
be visible by calling Show().

Within the BeOS, each BWindow object runs in its own thread.  What this means is that 
each time you create a BWindow object, behind the scenes a message loop is created 
(BWindow derives from BLooper) and is automatically set to start running (thus we 
don't have to call Run() explicitly.)  When the user clicks in the window "go-away" box, essentially we are 
quitting the window thread.  So whenever the user closes the window, QuitRequested() is 
called.  In the case of BWindow, QuitRequested() will return true as a default and will 
delete the window.

In our case, we want to do one more thing.  If the user closes the window, we also 
want the HelloWorld application to quit.  So, we override QuitRequested().  There are a 
couple of ways to tell the application to quit.  In this case, we post 
the B_QUIT_REQUESTED message to the application.  be_app is a global variable available 
within any application 
that simply points to the the application object, so we can use be_app to 
PostMessage(B_QUIT_REQUESTED).  What happens is that a new quit message is sent from the window thread to the application 
thread.  We need to return true so that the inherited BWindow features of HelloWindow 
will finish closing the window properly, and quitting the windows thread.  At the same time, 
the application is picking up the quit message we sent and beginning to shut down 
the entire application.  Though trivial in this case, this parallelism is an important 
part of the BeOS, and will be used often in more complex applications.

Now that we have defined the window and view, we can complete the application implementation;


// -----------------------------------------------------------------------
// HelloWorldApp.cp
// -----------------------------------------------------------------------
     
     #include "HelloWorldApp.h"
     #include "HelloWindow.h"

     main()
     {
          HelloWorldApp*     myApplication;
          myApplication = new HelloWorldApp();
          myApplication-&gt;Run();
          delete myApplication;
          return 0;    
     }


     HelloWorldApp::HelloWorldApp()     : BApplication('HLWD')
     {
          BRect     frameRect;
          frameRect.Set(100,100,280,140);
          HelloWindow*  theWindow = new HelloWindow(frameRect);
     }


We've added an #include to bring in the HelloWindow header, and we've added a body 
to the constructor.  When the application is created, a window is automatically created 
as well, placed at (100,100,280,140) on the screen.  The application simply needs 
to create the window - the HelloWindow does the rest of the work as we've defined above.

You may have noticed that we've said nothing about creating or operating the application 
menu.  And we've done nothing to set up the "About HelloWorld" dialog box either. 
 There is a simple reason for this - it is handled automatically for you by the BApplication 
 object.  Unless you specifically override these feature in your own application 
object, BApplication creates a main menu with "About &lt;app name&gt;.." and Quit, and 
will create an BAlert window for the "About" dialog when the user selects it.  It 
also assumes that if the user chooses "Quit", the application should tear down its windows 
and terminate.  You don't have to handle mouse events in the menu or the "About" 
box any more than you have to worry about moving windows around - these are all default 
behaviors of the BeOS objects we've already created within HelloWorldApp.

Once complete, our CodeWarrior project should look something like the window below.


Completed CodeWarrior project for HelloWorld

We can then make the project (Project menu/make.)  Make sure that within CodeWarrior 
you've set the project preferences to name the application "HelloWorld", otherwise 
the name of the application will be "Application"  Another exercise that might be 
useful is to take HelloWorld and modify it so that a "Quit" button appears in the window 
as well, which would close the window and quit the application.  This would simply 
take the BView and messaging approaches we've already used here and apply it to a 
different type of interface object.

This paper has provided an introductory overview of programming in the BeOS.  For 
further information and sample code, take a look at the Developer area on the Be 
web site (http://www.be.com)  You may also want to take a look at the BeBook, the 
API of the BeOS, to get a more thorough overview of the BeOS Kits and other objects.
